import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_web_view/widget/f_webview/webview_controller.dart';
import 'package:flutter_web_view/widget/f_webview/webview_strategy.dart';
import 'package:webview_windows/webview_windows.dart';

/// webview_windows 实现，支持Windows平台
class WebViewWindowsStrategy extends StatefulWidget implements WebViewStrategy {
  const WebViewWindowsStrategy({
    Key? key,
    required this.initialUrl,
    this.onTitleChanged,
    this.onWebViewCreated,
    this.onProgressChanged,
    this.onLoadStop,
  }) : super(key: key);

  @override
  State<StatefulWidget> createState() {
    return WebViewWindowsStrategyState();
  }

  @override
  final String initialUrl;

  @override
  final void Function(FWebViewController controller, String? url)?
      onTitleChanged;

  @override
  final void Function(FWebViewController controller)? onWebViewCreated;

  @override
  final void Function(FWebViewController controller, int progress)?
      onProgressChanged;

  @override
  final void Function(FWebViewController controller, String? url)? onLoadStop;
}

class WebViewWindowsStrategyState extends State<WebViewWindowsStrategy>
    implements FWebViewController {
  final navigatorKey = GlobalKey<NavigatorState>();

  /// 是否可以返回
  bool _isCanGoBack = false;

  /// 是否可以后退
  bool _isCanGoForward = false;

  /// 当前的title
  String _currentTitle = "";

  /// 当前加载的url
  String _currentUrl = "";

  /// WebView控制器
  final _controller = WebviewController();

  @override
  void initState() {
    super.initState();
    initPlatformState();
  }

  /// 初始化
  Future<void> initPlatformState() async {
    try {
      await _controller.initialize();
      await _controller.setBackgroundColor(Colors.transparent);
      await _controller.setPopupWindowPolicy(WebviewPopupWindowPolicy.deny);
      await _controller.loadUrl(widget.initialUrl);

      /// 监听加载进度
      _controller.loadingState.listen((event) {
        if (event == LoadingState.none) {
          // 没有加载
          if (widget.onProgressChanged != null) {
            widget.onProgressChanged!(this, 0);
          }
        } else if (event == LoadingState.loading) {
          // 加载中
          if (widget.onProgressChanged != null) {
            widget.onProgressChanged!(this, 90);
          }
        } else if (event == LoadingState.navigationCompleted) {
          // 加载完毕
          if (widget.onProgressChanged != null) {
            widget.onProgressChanged!(this, 100);
          }
          // 通知加载页面完毕
          if (widget.onLoadStop != null) {
            widget.onLoadStop!(this, _currentUrl);
          }
        }
      });

      // 监听前进、后退的变化
      _controller.historyChanged.listen((event) {
        setState(() {
          _isCanGoBack = event.canGoBack;
          _isCanGoForward = event.canGoForward;
        });
      });

      // 监听url变化
      _controller.url.listen((url) {
        setState(() {
          _currentUrl = url;
        });
      });

      // 监听title变化
      _controller.title.listen((title) {
        setState(() {
          _currentTitle = title;
        });
        if (widget.onTitleChanged != null) {
          widget.onTitleChanged!(this, title);
        }
      });

      if (!mounted) {
        return;
      }
      setState(() {
        // 通知创建完成
        widget.onWebViewCreated!(this);
      });
    } on PlatformException catch (e) {
      WidgetsBinding.instance.addPostFrameCallback((_) {
        showDialog(
            context: context,
            builder: (_) => AlertDialog(
                  title: const Text('发生了错误'),
                  content: Column(
                    mainAxisSize: MainAxisSize.min,
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: [
                      Text('错误码: ${e.code}'),
                      Text('错误信息: ${e.message}'),
                    ],
                  ),
                  actions: [
                    TextButton(
                      child: const Text('退出'),
                      onPressed: () {
                        Navigator.of(context).pop();
                      },
                    )
                  ],
                ));
      });
    }
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  /// 权限申请
  Future<WebviewPermissionDecision> _onPermissionRequested(
      String url, WebviewPermissionKind kind, bool isUserInitiated) async {
    final decision = await showDialog<WebviewPermissionDecision>(
      context: navigatorKey.currentContext!,
      builder: (BuildContext context) => AlertDialog(
        title: const Text('WebView 权限请求'),
        content: Text('WebView 需要权限： \'$kind\''),
        actions: <Widget>[
          TextButton(
            onPressed: () =>
                Navigator.pop(context, WebviewPermissionDecision.deny),
            child: const Text('拒绝'),
          ),
          TextButton(
            onPressed: () =>
                Navigator.pop(context, WebviewPermissionDecision.allow),
            child: const Text('同意'),
          ),
        ],
      ),
    );
    return decision ?? WebviewPermissionDecision.none;
  }

  @override
  Widget build(BuildContext context) {
    // 未初始化
    if (!_controller.value.isInitialized) {
      return const Text(
        '',
        style: TextStyle(
          fontSize: 24.0,
          fontWeight: FontWeight.w900,
        ),
      );
    } else {
      // 初始化完成
      return Webview(
        _controller,
        permissionRequested: _onPermissionRequested,
      );
    }
  }

  @override
  Future<bool> canGoBack() {
    return Future.sync(() => _isCanGoBack);
  }

  @override
  Future<bool> canGoForward() {
    return Future.sync(() => _isCanGoForward);
  }

  @override
  Future<String?> getTitle() {
    return Future.sync(() => _currentTitle);
  }

  @override
  Future<String?> getUrl() {
    return Future.sync(() => _currentUrl);
  }

  @override
  Future<void> goBack() {
    return _controller.goBack();
  }

  @override
  Future<void> goForward() {
    return _controller.goForward();
  }

  @override
  Future<void> loadUrl(String url) {
    return _controller.loadUrl(url);
  }

  @override
  Future<void> reload() {
    return _controller.reload();
  }
}
